/*
 * ModelParametersComponent.java
 *
 * Created on 8 de Julho de 2011, 15:51
 */

package intopo.demonstrator.partnerclassification.gui;

import intopo.demonstrator.partnerclassification.Parameters;
import intopo.demonstrator.Event;
import util.math.Rational;

import java.awt.Color;
import java.beans.*;
import javax.swing.JTextField;
import javax.swing.event.DocumentEvent;

/**
 *
 * @author  pedro
 */
public class ModelParametersComponent
	extends javax.swing.JPanel
	implements
		java.io.Serializable
{
	/**
	 * Name of the parameters property.
	 */
	static public String PARAMETERS_PROPERTY = "parameters";
//	/**
//	 * The parameters of the Partner Classification model that are being shown/edited by this component.
//	 */
//	private Parameters parameters;
	transient private TableModelCandidatePartners model;
	/**
	 */
	private PropertyChangeSupport propertySupport;
	transient private Listener listener;
	/** Creates new form BeanForm */
	public ModelParametersComponent ()
	{
		propertySupport = new PropertyChangeSupport (this);
		model = new TableModelCandidatePartners ();
		listener = new Listener ();
		initComponents ();
		updateComponents ();
	}
//	/**
//	 * Return the parameters that are being shown/edited by this component.
//	 */
//	public Parameters getParameters ()
//	{
//		return this.parameters;
//	}
//	/**
//	 * Set the parameters that are being shown/edited by this component.
//	 */
//	public void setParameters (Parameters p)
//	{
//		Parameters oldParameters = this.parameters;
//		this.parameters = p;
//		propertySupport.firePropertyChange (PARAMETERS_PROPERTY, oldParameters, this.parameters);
//		removeListener ();
//		poolSizeTextField.setText (String.valueOf (parameters.getPoolSize ()));
//		bitsProbabilityTextField.setText (String.valueOf (parameters.getNumberBitsProbability ()));
//		bitsWeightTextField.setText (String.valueOf (parameters.getNumberBitsWeight ()));
//		deltaTextField.setText (parameters.getDelta ().toString ());
//		numberPartnersFormattedTextField.setText (String.valueOf (parameters.getCombinationSize ()));
//		model.fireTableDataChanged ();
//		addListener ();
//	}
	/**
	 * Update the data in the components of this form with the parameters of the partner classification model.
	 */
	private void updateComponents ()
	{
		removeListener ();
		poolSizeTextField.setText (String.valueOf (Model.parameters.getPoolSize ()));
		bitsProbabilityTextField.setText (String.valueOf (Model.parameters.getNumberBitsProbability ()));
		bitsWeightTextField.setText (String.valueOf (Model.parameters.getNumberBitsWeight ()));
		deltaTextField.setText (Model.parameters.getDelta ().toString ());
		numberPartnersFormattedTextField.setText (String.valueOf (Model.parameters.getCombinationSize ()));
		model.fireTableDataChanged ();
		addListener ();
	}
	private void addListener ()
	{
		poolSizeTextField.getDocument ().addDocumentListener (listener);
		bitsProbabilityTextField.getDocument ().addDocumentListener (listener);
		bitsWeightTextField.getDocument ().addDocumentListener (listener);
		deltaTextField.getDocument ().addDocumentListener (listener);
		numberPartnersFormattedTextField.getDocument ().addDocumentListener (listener);
	}
	private void removeListener ()
	{
		poolSizeTextField.getDocument ().removeDocumentListener (listener);
		bitsProbabilityTextField.getDocument ().removeDocumentListener (listener);
		bitsWeightTextField.getDocument ().removeDocumentListener (listener);
		deltaTextField.getDocument ().removeDocumentListener (listener);
		numberPartnersFormattedTextField.getDocument ().removeDocumentListener (listener);
	}
	/** This method is called from within the constructor to
	 * initialize the form.
	 * WARNING: Do NOT modify this code. The content of this method is
	 * always regenerated by the Form Editor.
	 */
   // <editor-fold defaultstate="collapsed" desc=" Generated Code ">//GEN-BEGIN:initComponents
   private void initComponents() {
      javax.swing.JButton addPartnerButton;
      java.awt.GridBagConstraints gridBagConstraints;
      javax.swing.JLabel jLabel1;
      javax.swing.JLabel jLabel2;
      javax.swing.JLabel jLabel3;
      javax.swing.JLabel jLabel4;
      javax.swing.JLabel jLabel5;
      javax.swing.JPanel jPanel1;
      javax.swing.JScrollPane jScrollPane1;
      javax.swing.JButton removePartnerButton;

      jLabel1 = new javax.swing.JLabel();
      poolSizeTextField = new javax.swing.JTextField();
      jLabel2 = new javax.swing.JLabel();
      deltaTextField = new javax.swing.JTextField();
      jLabel3 = new javax.swing.JLabel();
      bitsProbabilityTextField = new javax.swing.JTextField();
      jLabel4 = new javax.swing.JLabel();
      numberPartnersFormattedTextField = new javax.swing.JFormattedTextField();
      jPanel1 = new javax.swing.JPanel();
      editPanel = new javax.swing.JPanel();
      addPartnerButton = new javax.swing.JButton();
      removePartnerButton = new javax.swing.JButton();
      jScrollPane1 = new javax.swing.JScrollPane();
      candidatePartnersTable = new javax.swing.JTable();
      jLabel5 = new javax.swing.JLabel();
      bitsWeightTextField = new javax.swing.JTextField();

      setLayout(new java.awt.GridBagLayout());

      setBorder(javax.swing.BorderFactory.createTitledBorder("parameters"));
      jLabel1.setText("pool size: ");
      gridBagConstraints = new java.awt.GridBagConstraints();
      gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST;
      add(jLabel1, gridBagConstraints);

      poolSizeTextField.setColumns(10);
      gridBagConstraints = new java.awt.GridBagConstraints();
      gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
      add(poolSizeTextField, gridBagConstraints);

      jLabel2.setText("delta: ");
      gridBagConstraints = new java.awt.GridBagConstraints();
      gridBagConstraints.gridy = 1;
      gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST;
      add(jLabel2, gridBagConstraints);

      deltaTextField.setColumns(5);
      gridBagConstraints = new java.awt.GridBagConstraints();
      gridBagConstraints.gridy = 1;
      gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
      add(deltaTextField, gridBagConstraints);

      jLabel3.setText("#bits probability: ");
      gridBagConstraints = new java.awt.GridBagConstraints();
      gridBagConstraints.gridy = 2;
      gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST;
      add(jLabel3, gridBagConstraints);

      bitsProbabilityTextField.setColumns(10);
      gridBagConstraints = new java.awt.GridBagConstraints();
      gridBagConstraints.gridy = 2;
      gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
      add(bitsProbabilityTextField, gridBagConstraints);

      jLabel4.setText("number partners: ");
      gridBagConstraints = new java.awt.GridBagConstraints();
      gridBagConstraints.gridy = 4;
      gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST;
      add(jLabel4, gridBagConstraints);

      numberPartnersFormattedTextField.setColumns(10);
      numberPartnersFormattedTextField.setToolTipText("Probability to draw an acceptable combination");
      gridBagConstraints = new java.awt.GridBagConstraints();
      gridBagConstraints.gridy = 4;
      gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
      add(numberPartnersFormattedTextField, gridBagConstraints);

      jPanel1.setLayout(new java.awt.BorderLayout());

      jPanel1.setBorder(javax.swing.BorderFactory.createTitledBorder("candidate partners"));
      addPartnerButton.setText("Add");
      addPartnerButton.addActionListener(new java.awt.event.ActionListener() {
         public void actionPerformed(java.awt.event.ActionEvent evt) {
            addPartnerButtonActionPerformed(evt);
         }
      });

      editPanel.add(addPartnerButton);

      removePartnerButton.setText("Remove");
      removePartnerButton.addActionListener(new java.awt.event.ActionListener() {
         public void actionPerformed(java.awt.event.ActionEvent evt) {
            removePartnerButtonActionPerformed(evt);
         }
      });

      editPanel.add(removePartnerButton);

      jPanel1.add(editPanel, java.awt.BorderLayout.NORTH);

      jScrollPane1.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
      jScrollPane1.setPreferredSize(new java.awt.Dimension(200, 200));
      candidatePartnersTable.setModel(model);
      jScrollPane1.setViewportView(candidatePartnersTable);

      jPanel1.add(jScrollPane1, java.awt.BorderLayout.CENTER);

      gridBagConstraints = new java.awt.GridBagConstraints();
      gridBagConstraints.gridy = 5;
      gridBagConstraints.gridwidth = 2;
      gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
      add(jPanel1, gridBagConstraints);

      jLabel5.setText("#bits weight: ");
      gridBagConstraints = new java.awt.GridBagConstraints();
      gridBagConstraints.gridy = 3;
      gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST;
      add(jLabel5, gridBagConstraints);

      bitsWeightTextField.setColumns(10);
      gridBagConstraints = new java.awt.GridBagConstraints();
      gridBagConstraints.gridy = 3;
      gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
      add(bitsWeightTextField, gridBagConstraints);

   }// </editor-fold>//GEN-END:initComponents

	private void removePartnerButtonActionPerformed (java.awt.event.ActionEvent evt) {//GEN-FIRST:event_removePartnerButtonActionPerformed
		int row = this.candidatePartnersTable.getSelectedRow ();
		if (row != -1) {
			Model.parameters.deletePartnersDescription (row);
			model.fireTableDataChanged ();
			propertySupport.firePropertyChange ("parameters", null, Model.parameters);
		}
	}//GEN-LAST:event_removePartnerButtonActionPerformed

	private void addPartnerButtonActionPerformed (java.awt.event.ActionEvent evt) {//GEN-FIRST:event_addPartnerButtonActionPerformed
		Model.parameters.addPartnersDescription (new Event (new Rational (1, 2)), 1);
		model.fireTableDataChanged ();
		propertySupport.firePropertyChange ("parameters", null, Model.parameters);
	}//GEN-LAST:event_addPartnerButtonActionPerformed
	
	
   // Variables declaration - do not modify//GEN-BEGIN:variables
   private javax.swing.JTextField bitsProbabilityTextField;
   private javax.swing.JTextField bitsWeightTextField;
   private javax.swing.JTable candidatePartnersTable;
   private javax.swing.JTextField deltaTextField;
   private javax.swing.JPanel editPanel;
   private javax.swing.JFormattedTextField numberPartnersFormattedTextField;
   private javax.swing.JTextField poolSizeTextField;
   // End of variables declaration//GEN-END:variables
	
	public void addPropertyChangeListener (PropertyChangeListener listener)
	{
		propertySupport.addPropertyChangeListener (listener);
	}

	public void removePropertyChangeListener (PropertyChangeListener listener)
	{
		propertySupport.removePropertyChangeListener (listener);
	}
	/**
	 * Inner class that implements the document listener used by the text fields of the enclosing class.
	 */
	private class Listener
		implements
			javax.swing.event.DocumentListener,
			java.io.Serializable
	{
		public void changedUpdate (DocumentEvent e) {
			updateParameter (e);
		}
		public void insertUpdate (DocumentEvent e) {
			updateParameter (e);
		}
		public void removeUpdate (DocumentEvent e) {
			updateParameter (e);
		}
		/**
		 * Updates the parameter corresponding to the text field that caused the document event.
		 */
		private void updateParameter (DocumentEvent e)
		{
			javax.swing.JTextField tf = null;
			try {
				if (e.getDocument () == bitsProbabilityTextField.getDocument ()) {
					tf = bitsProbabilityTextField;
					Model.parameters.setNumberBitsProbability (Integer.parseInt (bitsProbabilityTextField.getText ()));
				}
				else if (e.getDocument () == bitsWeightTextField.getDocument ()) {
					tf = bitsWeightTextField;
					Model.parameters.setNumberBitsWeight (Integer.parseInt (bitsWeightTextField.getText ()));
				}
				else if (e.getDocument () == poolSizeTextField.getDocument ()) {
					tf = poolSizeTextField;
					Model.parameters.setPoolSize (Integer.parseInt (poolSizeTextField.getText ()));
				}
				else if (e.getDocument () == deltaTextField.getDocument ()) {
					tf = deltaTextField;
					Model.parameters.setDelta (new Rational (deltaTextField.getText ()));
				}
				else if (e.getDocument () == numberPartnersFormattedTextField.getDocument ()) {
					tf = numberPartnersFormattedTextField;
					Model.parameters.setCombinationSize (Integer.parseInt (numberPartnersFormattedTextField.getText ()));
				}
				else {
					throw new Error ("Not reachable");
				}
				tf.setForeground (Color.BLACK);
				propertySupport.firePropertyChange ("parameters", null, Model.parameters);
			}
			catch (NumberFormatException ex) {
				tf.setForeground (Color.RED);
			}
			catch (IllegalArgumentException ex) {
				ex.printStackTrace ();
				tf.setForeground (Color.MAGENTA);
			}
		}
	}


	/**
	 * This class provides the set of candidate partners to a {@code JTable}.
	 */
	private class TableModelCandidatePartners
		extends javax.swing.table.AbstractTableModel
	{
		public int getColumnCount ()
		{
			return 2;
		}
		public int getRowCount ()
		{
			return Model.parameters.getPartnersDescriptionSize ();
		}
		public boolean isCellEditable (int row, int column)
		{
			return true;
		}
		public Object getValueAt (int row, int column)
		{
			switch (column) {
			case 0:
				return Integer.toString (Model.parameters.getPartnersDescriptionQuantity (row));
			case 1:
				return Model.parameters.getPartnersDescriptionProbability (row).toString ();
			}
			return null;
		}
		public void setValueAt (Object o, int row, int column)
		{
			try {
				switch (column) {
				case 0:
					Model.parameters.setPartnersDescriptionQuantity (row, ((Integer) o).intValue ());
					break;
				case 1:
					Model.parameters.setPartnersDescriptionProbability (row, new Rational (o.toString ()));
					break;
				}
				propertySupport.firePropertyChange ("parameters", null, Model.parameters);
			}
			catch (Exception e) {
				System.err.println ("ModelParametersComponents.java class TableModelCandidatePartners method void setValueAt(Object,int,int)");
			}
		}
		public Class<?> getColumnClass (int column)
		{
			switch (column) {
			case 0:
				return Integer.class;
			case 1:
				return String.class;
			}
			return null;
		}
		public String getColumnName (int column)
		{
			switch (column) {
			case 0:
				return "quantity";
			case 1:
				return "acceptable probability";
			}
			return null;
		}
	}

}
